/*
Eteria IRC Client, an RFC 1459 compliant client program written in Java.
Copyright (C) 2001  Christian Buck <cbuck at lantis.de>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.IOException;
import java.util.*;
import java.text.Collator;
import java.text.MessageFormat;
import java.text.ParseException;

import ar.com.jkohen.irc.Channel;
import ar.com.jkohen.irc.User;
import ar.com.jkohen.irc.MircMessage;
import ar.com.jkohen.util.Resources;
import ar.com.jkohen.util.ConfigurationProperties;
import ar.com.jkohen.awt.ChatPanel;
import ar.com.jkohen.awt.MircSmileyTextArea;
import ar.com.jkohen.awt.NickInfo;
import ar.com.jkohen.awt.ImageButton;
import ar.com.jkohen.awt.BorderedPanel;
import com.splendid.awtchat.*;

class WhoListWindow extends ChatPanel implements ActionListener, ItemListener, HyperlinkReceiver, Observer
{
    private EIRC eirc;
    private String title;
	private MircSmileyTextArea text_canvas;
	private Vector users;

	public static final int SORT_BYNICK = 0;
	public static final int SORT_BYAGE = 1;
	public static final int SORT_BYLOCATION = 2;
	public static final int SORT_BYDOMAIN = 3;
	public static final int SORT_BYSEX = 4;
	
	private static int sort_criteria = SORT_BYNICK;
	private Collator collator;
	
	private static boolean FILTER_MALE = false;
	private static boolean FILTER_FEMALE = false;
	private static boolean FILTER_UNKNOWN = true;
	
	private Resources res;
	protected static final String age_string = Resources.getString("who_list.age");
	
	Checkbox sort_0, sort_1, sort_2, sort_3, sort_4;
	Checkbox male, female, unknown, invisible;
	
	BorderedPanel panel;
	ImageButton b;
	
	protected static final MessageFormat MALE_FORMAT = new MessageFormat(Resources.getString("msg.male"));
	protected static final MessageFormat FEMALE_FORMAT = new MessageFormat(Resources.getString("msg.female"));
	protected static final MessageFormat UNKNOWN_FORMAT = new MessageFormat(Resources.getString("msg.unknown"));
	

    public WhoListWindow(EIRC eirc, String title)
	{
    	super(title);
		text_canvas = new MircSmileyTextArea(this, null);

    	this.eirc = eirc;
    	this.title = title;
		this.collator = Collator.getInstance();
		
		text_canvas.setMode(eirc.scrollSpeed());
    	text_canvas.setBufferlen(1000);
        text_canvas.setBreaks(false);
        int tabs[] = {-1, 200, 250, 320};
        text_canvas.setTabs(tabs);

        GridBagLayout gb = new GridBagLayout();
    	GridBagConstraints gbc = new GridBagConstraints();
        setLayout(gb);

        gbc.insets = new Insets(2, 2, 2, 2);

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
		gbc.gridheight = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.fill = GridBagConstraints.BOTH;
    	gbc.weighty = 1;
      	gbc.weightx = 1;
    	gb.setConstraints(text_canvas, gbc);
    	add(text_canvas);
		
		invisible = new Checkbox(res.getString("who_list.invisible"));
      	gbc.weightx = 0;
    	gbc.weighty = 0;
        gbc.fill = GridBagConstraints.NONE;
		gbc.gridheight = 1;
		gbc.gridx++;
		gbc.anchor = GridBagConstraints.NORTH;
		gb.setConstraints(invisible, gbc);
    	add(invisible);
		
    	
    	panel = new BorderedPanel(Resources.getString("who_list.frame"));
    	GridBagLayout gb2 = new GridBagLayout();
    	GridBagConstraints gbc2 = new GridBagConstraints();
    	panel.setLayout(gb2);

    	gbc2.weightx = 1.0;
        gbc2.insets = new Insets(0, 2, 0, 2);

		gbc2.gridx = 0;
		gbc2.gridy = 0;
		gbc2.anchor = GridBagConstraints.WEST;
		Label l = new Label(res.getString("who_list.sort") + " :");
		gb2.setConstraints(l, gbc2);
    	panel.add(l);
    	
    	CheckboxGroup sort_group = new CheckboxGroup();
    	
		gbc2.gridy++;
    	sort_0 = new Checkbox(res.getString("who_list.sort.1"), sort_group, (sort_criteria == SORT_BYNICK));
		gb2.setConstraints(sort_0, gbc2);
    	panel.add(sort_0);
    	
    	gbc2.gridy++;
    	sort_1 = new Checkbox(res.getString("who_list.sort.2"), sort_group, (sort_criteria == SORT_BYAGE));
		gb2.setConstraints(sort_1, gbc2);
    	panel.add(sort_1);

    	gbc2.gridy++;
    	sort_2 = new Checkbox(res.getString("who_list.sort.3"), sort_group, (sort_criteria == SORT_BYSEX));
		gb2.setConstraints(sort_2, gbc2);
    	panel.add(sort_2);

    	gbc2.gridy++;
    	sort_3 = new Checkbox(res.getString("who_list.sort.4"), sort_group, (sort_criteria == SORT_BYDOMAIN));
		gb2.setConstraints(sort_3, gbc2);
    	panel.add(sort_3);
    	
    	gbc2.gridy++;
    	sort_4 = new Checkbox(res.getString("who_list.sort.5"), sort_group, (sort_criteria == SORT_BYLOCATION));
		gb2.setConstraints(sort_4, gbc2);
    	panel.add(sort_4);
    	
    	gbc2.gridy++;
    	gbc2.gridwidth = 2;
    	gbc2.anchor = GridBagConstraints.CENTER;
        b = new ImageButton(res.getString("who_list.refresh"));
		b.setWaitType();
        b.setEnabled(true);
    	b.setActionCommand("list");
        gb2.setConstraints(b, gbc2);
        
        gbc.anchor = GridBagConstraints.NORTH;
        gb.setConstraints(panel, gbc);
    	panel.add(b);
    	
    	gbc2.gridy = 0;
    	gbc2.gridx++;
    	gbc2.gridwidth = 1;

		l = new Label(res.getString("who_list.check") + " :");
		gbc2.anchor = GridBagConstraints.WEST;
		gb2.setConstraints(l, gbc2);
    	panel.add(l);
    	
 		gbc2.gridy++;
    	male = new Checkbox(res.getString("who_list.male"), !FILTER_MALE);
		gb2.setConstraints(male, gbc2);
    	panel.add(male);
    	
		gbc2.gridy++;
    	female = new Checkbox(res.getString("who_list.female"), !FILTER_FEMALE);
		gb2.setConstraints(female, gbc2);
    	panel.add(female);
    	
		gbc2.gridy++;
    	unknown = new Checkbox(res.getString("who_list.unknown"), !FILTER_UNKNOWN);
		gb2.setConstraints(unknown, gbc2);
    	panel.add(unknown);
		

		gbc.weightx = 0;
      	gbc.weighty = 1;
		gbc.gridy++;
        gb.setConstraints(panel, gbc);
    	add(panel);

		b.addActionListener(this);
    	sort_0.addItemListener(this);
    	sort_1.addItemListener(this);
    	sort_2.addItemListener(this);
    	sort_3.addItemListener(this);
    	sort_4.addItemListener(this);
    	male.addItemListener(this);
    	female.addItemListener(this);
    	unknown.addItemListener(this);
		invisible.addItemListener(this);
    }
	
	public void clear()
	{
		text_canvas.clear();
	}
	
	public void loadUsers(Vector data)
    {
//		Vector users = NickInfo.getList();
		this.users = data;		
		display();
	}
    	
	private void display()
	{
		text_canvas.setMode(text_canvas.SAFE);
    	text_canvas.clear();
		
		if (users != null)
		{
    		sort(users);
    		
    		boolean display = true;
    		
          	for (Enumeration e = users.elements(); e.hasMoreElements(); )
          	{
    			String nick = e.nextElement().toString();
        	    
        	    int a = NickInfo.getAge(nick);
				String age = (a > 0 ? String.valueOf(a) + " " + age_string : "-");
        	    	
        	    String desc = NickInfo.getLocation(nick);
        	    String country = NickInfo.getCountry(nick);
        	    
        	    display = true;
        	    MessageFormat mf;
        	    switch(NickInfo.getSex(nick))
        	    {
        	    case NickInfo.SEX_MALE:
        	    	mf = MALE_FORMAT;
        	    	if (FILTER_MALE)
        	    		display = false;
        	    	break;
        	    case NickInfo.SEX_FEMALE:
        	    	mf = FEMALE_FORMAT;
        	    	if (FILTER_FEMALE)
        	    		display = false;
        	    	break;
        	    default:
        	    	mf = UNKNOWN_FORMAT;
        	    	if (FILTER_UNKNOWN)
        	    		display = false;
        	    	break;
        	    }
    			
    			if (invisible.getState() && eirc.getNick().equals(nick))
    				display = false;

    			if (display)
    			{
    				Object o[] = { nick, "", MircMessage.COLOR + "3 " + age + MircMessage.COLOR + "12 " + country + MircMessage.RESET + desc };
        		    text_canvas.appendNickInfo(mf.format(o), true, nick);
        		}
            }
		}
        
        text_canvas.setMode(eirc.scrollSpeed());
		text_canvas.home();
        b.setEnabled(true);
	}
	
	// Sorting algorithm from James Gosling
	
	private void sort(Vector v)
    {
        sort(v, 0, v.size() - 1);
    }
	
    private void sort(Vector v, int i, int j)
    {
        int k = i;
        int l = j;
        if(k >= l)
        	return;
		else
			if(k == l - 1)
			{
				Object a = v.elementAt(k);
				Object b = v.elementAt(l);
				if (compare(a, b) < 0)
				{
					v.setElementAt(b, k);
					v.setElementAt(a, l);
				}
			}
			
        Object a = v.elementAt((k + l) / 2);
		v.setElementAt(v.elementAt(l), (k + l) / 2);
		v.setElementAt(a, l);
		
        while(k < l) 
        {
            while(k < l && compare(a, v.elementAt(k)) >= 0) 
                k++;
            while(k < l && compare(a, v.elementAt(l)) <= 0)
				l--;
            if(k < l)
            {
				Object o = v.elementAt(k);
				v.setElementAt(v.elementAt(l), k);
				v.setElementAt(o, l);
            }
        }
        v.setElementAt(v.elementAt(l), j);
		v.setElementAt(a, l);
				
        sort(v, i, k - 1);
        sort(v, l + 1, j);
    }
	
	private int compare(Object o1, Object o2)
	{
		int comp = 0;
		String nick1 = o1.toString();
		String nick2 = o2.toString();
			
		switch (sort_criteria)
		{
   	    case SORT_BYNICK:
      		comp = collator.compare(nick1, nick2);
      		break;
		case SORT_BYAGE:
			comp = NickInfo.getAge(nick1) - NickInfo.getAge(nick2);
			break;
		case SORT_BYLOCATION:
			comp = collator.compare(NickInfo.getLocation(nick1), NickInfo.getLocation(nick2));
            break;
		case SORT_BYDOMAIN:
        	comp = collator.compare(NickInfo.getCountry(nick1), NickInfo.getCountry(nick2));
        	break;
		case SORT_BYSEX:
        default:
        	comp = NickInfo.getSex(nick2) - NickInfo.getSex(nick1);
        	break;
		}
		return(comp);
	}
	
	public void updateBackground(Container ct, Color cl)
    {
		ct.setBackground(cl);
		Component cp[] = ct.getComponents();
		for (int i = 0; i < cp.length; i++)
		{
			if (cp[i] instanceof Container)
				updateBackground((Container)cp[i], cl);
			else
				if (!(cp[i] instanceof TextField))
					cp[i].setBackground(cl);
		}
    }
	
    public void setBackground(Color c)
    {
        super.setBackground(c);
		invisible.setBackground(c);
		updateBackground((Container)panel, c);
    }

    public void setTextBackground(Color c)
    {
		text_canvas.setBackground(c);
    }
	
    public void setForeground(Color c)
    {
        super.setForeground(c);
    }

    public void setSelectedBackground(Color c)
	{
		text_canvas.setSelectedBackground(c);
    }

    public void setSelectedForeground(Color c)
    {
//        visualTree.setSelectedForeground(c);
    }

    public void setFont(Font f)
    {
		super.setFont(f);
		text_canvas.setFont(f);
    }
    
    public void actionPerformed(ActionEvent ev)
    {
		String ac = ev.getActionCommand();
	    
	    if (ac.equals("list"))
		{
			b.setEnabled(false);
			NickInfo.clear();
			
			String p1[] = { };
			eirc.sendMessage("LUSERS", p1);

			String p2[] = { "*" };
	    	eirc.sendMessage("WHO", p2);
	    }
    }
    
    public void itemStateChanged(ItemEvent ev)
    {
	    if (ev.getSource() == sort_0)
	    	sort_criteria = SORT_BYNICK;
	    if (ev.getSource() == sort_1)
	    	sort_criteria = SORT_BYAGE;
	    if (ev.getSource() == sort_2)
	    	sort_criteria = SORT_BYSEX;
	    if (ev.getSource() == sort_3)
	    	sort_criteria = SORT_BYDOMAIN;
		if (ev.getSource() == sort_4)
	    	sort_criteria = SORT_BYLOCATION;
	    if (ev.getSource() == male)
	    	FILTER_MALE = !male.getState();
	    if (ev.getSource() == female)
	    	FILTER_FEMALE = !female.getState();
		if (ev.getSource() == unknown)
	    	FILTER_UNKNOWN = !unknown.getState();
			
		if (ev.getSource() == invisible)
		{
	    	String p[] = { eirc.getNick(), (invisible.getState() ? "+" : "-") + "i" };
		    eirc.sendMessage("MODE", p);
		}
			
	    display();
    }
	
    public void update(Observable o, Object arg)
    {
		ConfigurationProperties props = (ConfigurationProperties) o;

		if (arg == null || arg.equals("scroll_speed"))
	    	text_canvas.setMode(props.getInt("scroll_speed"));
    }

    public void handleHyperlink(String link)
    {
		if (Channel.isChannel(link))
		{
		    joinChannel(link);
 		}
 		else
 		{
	 	   try
	 	   {
				visitURL(new URL(link));
	 	   }
	 	   catch (MalformedURLException e)
	 	   {
	 	   }
		}
    }
    
    public void handleNick(String nick)
    {
		eirc.openPrivate(nick);
		eirc.showPanel(nick);
    }
    
    protected void visitURL(URL url)
    {
		eirc.visitURL(url);
    }
    
    protected void joinChannel(String name)
    {
		eirc.joinChannel(name);
    }
}
